from flask import Blueprint, request, session
from app.models.user import User
from app import db, redis_client
from app.utils import ResponseUtil
from app.session_utils import SessionManager
import uuid
import json
import time
import hashlib
import random
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from app.config import Config

auth_bp = Blueprint('auth', __name__, url_prefix='/auth')

@auth_bp.route('/register', methods=['POST'])
def register():
    try:
        data = request.get_json()
        
        # Validate required fields
        required_fields = ['username', 'password', 'email', 'avatar', 'verification_code']
        for field in required_fields:
            if not data or not data.get(field):
                return ResponseUtil.error(message=f"{field} is required", status_code=400)
        
        # Validate verification code
        stored_code = redis_client.get(f"verification_code:{data['email']}")
        if not stored_code:
            return ResponseUtil.error(message="Verification code has expired or not requested", status_code=401)
        
        if stored_code.decode('utf-8') != data['verification_code']:
            return ResponseUtil.error(message="Invalid verification code", status_code=400)
        
        # Check if user already exists
        if User.query.filter_by(username=data['username']).first():
            return ResponseUtil.error(message="Username already exists", status_code=409)
        
        if User.query.filter_by(email=data['email']).first():
            return ResponseUtil.error(message="Email already exists", status_code=409)
        
        # Hash the password
        hashed_password = hashlib.sha256(data['password'].encode('utf-8')).hexdigest()
        
        # Create new user
        user = User(
            username=data['username'],
            email=data['email'],
            password=hashed_password,
            avatar=data['avatar']
        )
        
        db.session.add(user)
        db.session.commit()
        
        # Remove used verification code
        redis_client.delete(f"verification_code:{data['email']}")
        
        return ResponseUtil.success(message="User created successfully")
        
    except Exception as e:
        db.session.rollback()
        return ResponseUtil.error(message="Failed to create user", status_code=500)

@auth_bp.route('/login', methods=['POST'])
def login():
    try:
        data = request.get_json()

        # Validate required fields
        required_fields = ['username', 'password']
        for field in required_fields:
            if not data or not data.get(field):
                return ResponseUtil.error(message=f"{field} is required", status_code=400)
        
        user = User.query.filter_by(username=data['username']).first()
        if user:
            # Hash the provided password for comparison
            hashed_password = hashlib.sha256(data['password'].encode('utf-8')).hexdigest()
            
            # Check password
            if user.password != hashed_password:
                return ResponseUtil.error(message="Invalid credentials", status_code=401)
            
            # Create a new session (this will automatically invalidate any previous session)
            session_token = SessionManager.create_session(user.id, user.username)
            
            # Return only the token
            token_data = {
                'token': session_token,
                'expires_in': 86400  # 24 hours in seconds
            }
            
            return ResponseUtil.success(data=token_data, message="Login successful")
        else:
            return ResponseUtil.error(message="Invalid credentials", status_code=401)
            
    except Exception as e:
        print(e)
        return ResponseUtil.error(message="Login failed", status_code=500)
@auth_bp.route('/logout', methods=['POST'])
def logout():
    try:
        # Get token from request headers or body
        token = None
        if 'Authorization' in request.headers:
            auth_header = request.headers['Authorization']
            if auth_header.startswith('Bearer '):
                token = auth_header[7:]  # Remove 'Bearer ' prefix
        
        if not token:
            data = request.get_json()
            if data and 'token' in data:
                token = data['token']
        
        if not token:
            return ResponseUtil.error(message="Session token is required", status_code=400)
        
        # Remove session from Redis
        SessionManager.delete_session(token)
        
        return ResponseUtil.success(message="Logout successful")
        
    except Exception as e:
        return ResponseUtil.error(message="Logout failed", status_code=500)

@auth_bp.route('/verification-code', methods=['POST'])
def send_verification_code():
    try:
        data = request.get_json()
        
        # Validate required fields
        if not data or not data.get('email'):
            return ResponseUtil.error(message="Email is required", status_code=400)
        
        # Generate a simple 6-digit code
        verification_code = str(random.randint(100000, 999999))
        
        # Store verification code in Redis with 10-minute expiration
        redis_client.setex(f"verification_code:{data['email']}", 600, verification_code)
        
        # Send verification code via email
        try:
            send_email_verification(data['email'], verification_code)
        except Exception as email_error:
            print(f"Failed to send email: {str(email_error)}")
            # Even if email fails, we still return success to the client
            # but log the error for debugging purposes
        
        # For security reasons, we don't return the code in production
        code_data = {
            'expires_in': 600
        }
        
        return ResponseUtil.success(data=code_data, message="Verification code sent successfully")
        
    except Exception as e:
        return ResponseUtil.error(message="Failed to send verification code", status_code=500)

def send_email_verification(email, verification_code):
    """
    Send verification code via email
    
    Args:
        email (str): Recipient email address
        verification_code (str): 6-digit verification code
    """
    # Create message container
    message = MIMEMultipart('alternative')
    message['Subject'] = Header("Your Verification Code", 'utf-8')
    message['From'] = Header(Config.MAIL_DEFAULT_SENDER or Config.MAIL_USERNAME, 'utf-8')
    message['To'] = Header(email, 'utf-8')
    
    # Create HTML content
    html_content = f"""
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>邮件验证码</title>
    </head>
    <body style="margin: 0; padding: 0; font-family: 'Helvetica Neue', Arial, sans-serif; background-color: #f8f9fa; color: #333;">
        <div style="max-width: 600px; margin: 30px auto; background: #ffffff; border-radius: 10px; box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);">
            <!-- Header -->
            <div style="background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%); padding: 30px; text-align: center; border-radius: 10px 10px 0 0;">
                <h1 style="color: white; margin: 0; font-size: 28px; font-weight: bold;">Verification Code</h1>
                <p style="color: rgba(255, 255, 255, 0.9); margin: 10px 0 0 0; font-size: 16px;">Your security is our priority</p>
            </div>
            
            <!-- Content -->
            <div style="padding: 30px;">
                <h2 style="color: #333; margin-top: 0;">尊敬的用户您好,</h2>
                
                <p style="font-size: 16px; line-height: 1.6;">以下是您申请的邮件验证码,请按照下列提示完成验证:</p>
                
                <!-- Verification Code Box -->
                <div style="background-color: #f8f9fa; border: 2px dashed #6a11cb; border-radius: 8px; padding: 25px; text-align: center; margin: 30px 0; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);">
                    <p style="margin: 0 0 10px 0; color: #666; font-size: 14px;">您的验证码是:</p>
                    <div style="font-size: 36px; font-weight: bold; color: #6a11cb; letter-spacing: 8px; margin: 10px 0;">{verification_code}</div>
                    <p style="margin: 10px 0 0 0; color: #999; font-size: 13px;">验证码在10分钟内有效</p>
                </div>
                
                <p style="font-size: 14px; line-height: 1.6;">如您未申请验证码，您可以安全的忽略这封邮件. 您的账号仍然是安全的.</p>
                
                <div style="background-color: #fff8e1; border-left: 4px solid #ffc107; padding: 15px; margin: 25px 0; border-radius: 0 4px 4px 0;">
                    <p style="margin: 0; font-size: 14px; color: #333;">
                        <strong>安全提醒:</strong> 请不要分享此验证码给其他人
                    </p>
                </div>
            </div>
            
            <!-- Footer -->
            <div style="background-color: #f8f9fa; padding: 20px; text-align: center; border-radius: 0 0 10px 10px; border-top: 1px solid #eee;">
                <p style="margin: 0; color: #666; font-size: 12px;">
                    这是一封由 Union Form 系统自动发送的邮件，请勿直接回复邮件，如有疑问请你联系维护者。
                </p>
                <p style="margin: 5px 0 0 0; color: #999; font-size: 11px;">
                    &copy; 2025 Union Form. All rights reserved.
                </p>
            </div>
        </div>
    </body>
    </html>
    """
    
    # Create MIMEText object for HTML content
    html_part = MIMEText(html_content, 'html', 'utf-8')
    message.attach(html_part)
    
    # Connect to SMTP server and send email
    server = None
    try:
        if Config.MAIL_USE_SSL:
            server = smtplib.SMTP_SSL(Config.MAIL_SERVER, Config.MAIL_PORT)
        else:
            server = smtplib.SMTP(Config.MAIL_SERVER, Config.MAIL_PORT)
            if Config.MAIL_USE_TLS:
                server.starttls()
        
        if Config.MAIL_USERNAME and Config.MAIL_PASSWORD:
            server.login(Config.MAIL_USERNAME, Config.MAIL_PASSWORD)
            
        server.sendmail(Config.MAIL_DEFAULT_SENDER or Config.MAIL_USERNAME, email, message.as_string())
    finally:
        if server:
            server.quit()
        
@auth_bp.route('/session/validate', methods=['POST'])
def validate_session():
    try:
        # Get token from request
        data = request.get_json()
        if not data or 'token' not in data:
            return ResponseUtil.error(message="Token is required", status_code=400)
        
        token = data['token']
        
        # Check if session exists in Redis
        session_data = SessionManager.get_session(token)
        if not session_data:
            return ResponseUtil.error(message="Invalid or expired session", status_code=401)
        
        # Update last accessed time
        SessionManager.update_session(token)
        
        # Return session info without user details
        session_info = {
            'token': token,
            'user_id': session_data['user_id'],
            'username': session_data['username'],
            'login_time': session_data['login_time'],
            'last_accessed': session_data['last_accessed'],
            'expires_in': 86400
        }
        
        return ResponseUtil.success(data=session_info, message="Session is valid")
        
    except Exception as e:
        return ResponseUtil.error(message="Session validation failed", status_code=500)